/*
 * @Author: january.cjy
 * @Date: 2021-09-28 15:37:31
 * @Last Modified by: january.cjy
 * @Last Modified time: 2021-09-29 20:48:45
 */
#pragma once

#include "clang/Tooling/ArgumentsAdjusters.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"

#include "clang/Tooling/CommonOptionsParser.h"

namespace cmg {

using namespace llvm;
using namespace clang;
using namespace clang::tooling;

class CmgOptionsParser {
public:
  /// Parses command-line, initializes a compilation database.
  ///
  /// This constructor can change argc and argv contents, e.g. consume
  /// command-line options used for creating FixedCompilationDatabase.
  ///
  /// All options not belonging to \p Category become hidden.
  ///
  /// It also allows calls to set the required number of positional parameters.
  CmgOptionsParser(
      int &argc, const char **argv, llvm::cl::OptionCategory &Category,
      llvm::cl::NumOccurrencesFlag OccurrencesFlag = llvm::cl::ZeroOrMore,
      const char *Overview = nullptr);

  /// A factory method that is similar to the above constructor, except
  /// this returns an error instead exiting the program on error.
  static llvm::Expected<CmgOptionsParser>
  create(int &argc, const char **argv, llvm::cl::OptionCategory &Category,
         llvm::cl::NumOccurrencesFlag OccurrencesFlag,
         const char *Overview = nullptr);

  /// Returns a reference to the loaded compilations database.
  CompilationDatabase &getCompilations() { return *Compilations; }

  /// Returns a list of source file paths to process.
  const std::vector<std::string> &getSourcePathList() const {
    return SourcePathList;
  }
  /// Returns the argument adjuster calculated from "--extra-arg" and
  //"--extra-arg-before" options.
  ArgumentsAdjuster getArgumentsAdjuster() { return Adjuster; }

  int getConcurrentJobs() { return ConcurrentJobs; }

  static const char *const HelpMessage;

private:
  CmgOptionsParser() = default;

  llvm::Error init(int &argc, const char **argv,
                   llvm::cl::OptionCategory &Category,
                   llvm::cl::NumOccurrencesFlag OccurrencesFlag,
                   const char *Overview);

  std::unique_ptr<CompilationDatabase> Compilations;
  std::vector<std::string> SourcePathList;
  int ConcurrentJobs;
  ArgumentsAdjuster Adjuster;
};

} // namespace cmg